﻿#include "tcpserverfrm.h"
#include "ui_tcpserverfrm.h"

#include <QAction>
#include <QDateTime>
#include <QMetaEnum>
#include <QNetworkInterface>
#include <QStandardItemModel>

#include <net/netreading.h>
#include <net/netwriting.h>
#include <net/tcpserver.h>

QNET_USING_NAMESPACE
/**
 * @brief The Reading class 表示Tcp读取类。
 */
class Reading: public NetReading
{

public:
    Reading(TcpServerFrm *owner)
    {
        m_owner = owner;
    }
    ~Reading() override{}
    // TcpReading interface
public:
    void onProc(const QByteArray &arry) override
    {
        m_owner->onRecv(this, arry);
    }
private:
    TcpServerFrm *m_owner;
};

TcpServerFrm::TcpServerFrm(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::TcpServerFrm)
{
    ui->setupUi(this);
    m_server = Q_NULLPTR;
    m_curSession = Q_NULLPTR;

    QList<QHostAddress> iplist = QNetworkInterface::allAddresses();
    ui->comboBoxLocalAddr->addItem("0.0.0.0");  //
    foreach(auto host, iplist)
    {
        if(host.protocol() == QAbstractSocket::IPv6Protocol)
        {
            continue;
        }
        ui->comboBoxLocalAddr->addItem(host.toString());
        if(host.isLoopback() )
        {
            ui->comboBoxLocalAddr->setCurrentText(host.toString());
        }
    }
}

TcpServerFrm::~TcpServerFrm()
{
    delete ui;
}

void TcpServerFrm::onStateChanged(TcpSession *session, bool connected)
{
    QString msg ;
    QTextStream stream;
    stream.setString(&msg);
    QString itemName = QString("[%1:%2]").arg(session->remoteIp().toString()).arg(session->remotePort());
    if(connected )
    {
        session->setReading(new Reading(this));
        QVariant var = QVariant::fromValue(qintptr(session));
        QListWidgetItem *item = new QListWidgetItem(itemName, ui->listWidget);
        item ->setData(Qt::UserRole, var);
        ui->listWidget->addItem(item);

        stream << tr(" Session 连接成功！远端地址：") << itemName;
    }else {
        session->setReading(Q_NULLPTR);
        NetReading *reading = session->reading();
        delete reading;
        stream << tr("Remote point disconnect, point:") << itemName ;
        QListWidgetItem *findItem = Q_NULLPTR;
        int count = ui->listWidget->count();
        for (int i = 0; i < count; i++) {
            auto item = ui->listWidget->item(i);
            if(item->text() == itemName)
            {
                findItem = item;
                ui->listWidget->takeItem(i);
                break;
            }
        }
        if(findItem)
        {
            delete findItem;
        }
        if(m_curSession == session)
        {
            m_curSession = Q_NULLPTR;
        }
    }
    logAppend(msg);
}

void TcpServerFrm::onError(QAbstractSocket::SocketError error)
{
    QString msg;
    QTextStream stream(&msg);
    QMetaEnum metaEnum = QMetaEnum::fromType<QAbstractSocket::SocketError>();
    //枚举值转字符串
    stream << tr("Server 检测到socket错误信息：") << metaEnum.valueToKey(error);
    logAppend(msg);
}

void TcpServerFrm::on_btnListen_clicked()
{
    if(m_server)
    {
        m_server->deleteLater();
        m_server = Q_NULLPTR;
    }
    QString localAddr = ui->comboBoxLocalAddr->currentText();
    QHostAddress srcAddr(localAddr);

    quint16 srcPort = quint16(ui->spinSrcPort->value());

    m_server = new TcpServer(this, this);
    if(!m_server->listen(srcAddr, srcPort))
    {
        logAppend(tr("启动服务端失败！"));
        m_server->deleteLater();
        m_server = Q_NULLPTR;
        return ;
    }
    logAppend(tr("启动服务端成功！"));
    setServerStatus(true);
}

void TcpServerFrm::logAppend(QString msg)
{
    QString tmp = QString(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz"));
    tmp.append(msg);
    ui->textBrowser->append(tmp);
}

void TcpServerFrm::on_btnServerStop_clicked()
{
    if(m_server)
    {
        m_server->deleteLater();
        m_server = Q_NULLPTR;
        logAppend(tr("停止服务端！"));
    }
    setServerStatus(false);
}

void TcpServerFrm::on_btnClear_clicked()
{
    ui->textBrowser->clear();
}

void TcpServerFrm::setServerStatus(bool enable)
{
    ui->btnListen->setEnabled(!enable);
    ui->btnServerStop->setEnabled(enable);
}

void TcpServerFrm::onRecv(const NetReading *reading, const QByteArray &buffer)
{
    QHostAddress remoteAddr = reading->host();
    quint16 remotePort = reading->port();
    QString msg;
    QTextStream stream(&msg);
    stream << tr("接收到来自")  << remoteAddr.toString()
           << ":" << remotePort << tr("。") << buffer.size()
           << tr("字节数据 -- ") << QString::fromUtf8(buffer) ;
    logAppend(msg);
}

void TcpServerFrm::on_btnSend_clicked()
{
    QString msg;
    if(m_curSession)
    {
        QString sendText = ui->textEditSend->toPlainText();
        QByteArray sendArray = sendText.toUtf8();
        QSharedPointer<NetWriting> writing(
                    new NetWriting(sendArray, this),
                    &QObject::deleteLater);
        connect(writing.data(), &NetWriting::fulfil, this, &TcpServerFrm::fulfil_slot);
        if(m_curSession->write(writing))
        {
            msg = QString(tr("写入数据到发送队列成功！"));
        }else {
            msg = QString(tr("写入数据到发送队列失败！"));
        }
    }else {
        msg = QString(tr("请先选择会话"));
    }
    logAppend(msg);
}

void TcpServerFrm::fulfil_slot(QSharedPointer<NetWriting> owner, int size)
{
    QString msg  = QString(tr("原始数据%1字节。 发送。"))
            .arg(owner->size());

    QTextStream stream(&msg);
    if(size < 0)
    {
        stream << tr("失败！");
    }else {
        stream << tr("成功！");
    }
    logAppend(msg);
    ui->labSendSize->setNum(size);
}


void TcpServerFrm::on_listWidget_itemPressed(QListWidgetItem *item)
{
    QVariant var= item->data(Qt::UserRole);
    m_curSession = reinterpret_cast<TcpSession *>(var.value<qintptr>());
}
